    .MODEL   medium
    .CODE


   public	_asmsort
   public       _asmshow


rows            equ     18
record_len      equ     38


_asmshow                proc    far

        push    bp
        mov     bp,sp
        push    si
        push    di
        push    es
        push    ds

; open the file

        mov     bx, [bp+10]             ; which one in the array
        shl     bx, 1
        mov     si, [bp+8]              ; start of array
        mov     dx, [si+bx]             ; ds:dx points to filename of the
                                        ;  the file of interest
        mov     ax, 3d00h
        int     21h

        jnc     @@1
        jmp     error1

@@1:
        mov     [bp+8], ax              ; save the file handle

; allocate some memory

        mov     ah, 48h
        mov     bx, (rows * record_len)
        add     bx, 4                    ; 64 extra bytes
        int     21h
        jnc     @@2
        jmp     error1
@@2:
        mov     es, ax                  ; save the segment of our allocated memory

; zero out the buffer

        mov     di, 0
        mov     cx, (rows * record_len)
        mov     al, 13
        rep     stosb

        push    ds                      ; save ds
        mov     ax, es
        mov     ds, ax                  ; and point it to our new buffer

; read some data from the file

        mov     dx, 0                   ; ds:dx points to malloc buffer
        mov     ah, 3fh
        mov     bx, [bp+8]
        mov     cx, (rows * record_len)
        int     21h

close_handle:

        mov     ah, 3eh
        mov     bx, [bp+8]
        int     21h

        pop     ds                      ; ds restored, es still points to buffer


; populate the array.

        mov     si, [bp+6]              ; starting address of destination array

; first, zero it out

        push    es
        push    ds
        pop     es
        mov     di,si                   ; es:di points to start of myarray
        mov     cx, (rows * record_len)
        mov     al,0
        rep     stosb
        pop     es


; now fill in some lines

        mov     cx, rows
        mov     di, [bp+6]

        push    ds
        push    es                      ; save the segment registers
        push    ds
        push    es
        pop     ds                      ; swap the segment registers
        pop     es
        mov     si, 0                   ; ds:si -> data read from file

data_start:

        push    cx                      ; our line counter
        push    di
        mov     cx, record_len-6        ; save lots of space for the trailing 0

line_start:
        lodsb
        cmp     al, 13                  ; carriage return
        je      line_end2
        stosb
        loop    line_start

; OK, got to here and grabbed a whole line, but haven't seen a CR yet, so
;  run around until we do

cr_find:
        lodsb
        cmp     al, 13                  ; carriage return
        jne     cr_find
        jmp     line_end2

line_end2:
        lodsb                           ; skip the line feed

        mov     al, 0
        stosb
        pop     di
        add     di, record_len
        pop     cx
        loop    data_start

        pop     es
        pop     ds

; deallocate the memory

        mov     ah, 49h
        int     21h


error1:
        pop     ds
        pop     es
        pop     di
        pop     si
        pop     bp
        retf
_asmshow                endp


_asmsort                proc    far

        push    bp
        mov     bp,sp
        push    si
        push    di
        push    es
        push    ds

; how many files ?  this is REAL mode, and so we only want to deal with a 64K
;  segment

        mov     bx,[bp+8]               ; get the number of files previously
                                        ;  found
        cmp     bx, 4095                ; DOS ALLOC gets memory in 16 bytes
        ja      error                   ;  blocks
        cmp     bx,1                    ; is there anything to sort ?
        jbe     error

; allocate some memory for the sort

        mov     ah,48h
        int     21h
        jc      error
        mov     es,ax                   ; address of block

; grab the strings from the CNCPro array and stuff them into my array
;  as 0 terminated strings

        mov     cx,[bp+8]
        mov     si,[bp+6]               ; ds:si points to start of array
        mov     ax, [si]
        mov     si, ax                  ; di:si point to first record in

        call    move_to_my_array


; array in es:0, now sort it

        mov     cx,[bp+8]               ; cx has the number of items to sort

        call    sort


; grab the now sorted strings and plunk them back into the CNCPro array

        mov     cx,[bp+8]
        mov     si,[bp+6]               ; ds:si points to start of array
        mov     ax, [si]
        mov     si, ax                  ; di:si point to first record in the array

        call    move_from_my_array

; release the previously allocated memory

        mov     ah,49h
        int     21h

error:
        pop     ds
        pop     es
        pop     di
        pop     si
        pop     bp
        retf

_asmsort		endp


; reads the strings (of filenames) from the C style array, and moves them to
;  an area of memory previously allocated.
; this step is necessary as the C array has 24 byte long records, but
;  filenames are only 13 bytes long, 8.3 plus a zero.  there is therefore
;  11 bytes of crap that could mess up the sort routine
;
; called with     CX = number of elements in the array
;             ds:si -> first element in the array

move_to_my_array     proc    near

        mov     di,0                    ; point ot start of array

moveloop:
        push    cx
        push    si

; zero out the entire record prior to filling it

        mov     cx,12
        mov     al,0
        push    di
        rep     stosb
        pop     di

; move the string, right up to the trailing 0

        mov     cx,12
move_another:
        lodsb
        cmp     al,0
        je      string_end              ; trailing zero ?
        stosb
        loop    move_another
        jmp     end_move

string_end:
        mov     al,0                    ; string is less than 12 bytes long,
        rep     stosb                   ; so pad with zeroes

end_move:
        pop     si
        add     si,24                   ; point to the start of the next record
        pop     cx                      ; number of records remaining to process
        loop    moveloop
        ret
move_to_my_array     endp

; reads the strings (of filenames) from the area of memory previously allocated
; and moves them to the C style array.
;
; called with     CX = number of elements in the array
;             ds:si -> first element in the array

move_from_my_array     proc    near

        push    ds                      ; save the segment registers
        push    es

        push    ds                      ; swap the segment registers via
        push    es                      ; some ugly pushes and pops
        pop     ds
        pop     es

        push    si                      ; SI -> DI
        pop     di                      ;  DI points to start of C array
        mov     si,0                    ; SI points to start of my array

mft_loop:
        push    cx                      ; save the number of strings to process
        mov     cx,12
        rep     movsb                   ; move the string
        mov     al,0                    ; zero terminate it
        stosb
        add     di,11                   ; point to start of next record in C
                                        ;  array
        pop     cx                      ; recal number of strings to do
        loop    mft_loop

        pop     es                      ; recall segment registers
        pop     ds
        ret
move_from_my_array     endp



; alan's "sort" routine
; I make no claims as to the efficiency of the sort and a CS student will
;  probably laugh, but iit's the only way I could think of to sort things,
;  and it seems to work
;
; the logic is
;
;  compare strings 1 & 2 and swap if required (and set the swap flag)
;  compare strings 2 & 3 and swap if required ...
;  compare strings max-1 and max and swap if required ...
;
; return to top of routine and examine "swap flag".  if set, at least one
;  swap was performed and so run through the routine again
;
; continue until no swaps take place
;
; dx = flag if non-zero, a swap occurred
; called with    cx = number of elements to sort
;             ds:si -> start of the array to sort
;
; ------------------
sort    proc    near
; ------------------

        push    ds                      ; save segment register
        push    es                      ; DS = ES
        pop     ds

        dec     cx                      ; number of possible sorts is 1 less
                                        ;  than the number of elements
        mov     bx, cx                  ; save our count in a register (sorry
                                        ;  C guys, but I like registers)

sort_start0:
        mov     dx, 0                   ; indicate that no swaps are performed
        mov     cx,bx                   ; restore number of elements
        mov     si,0                    ; point ot first element
        mov     di,12                   ; point to second element

sort_start:

        push    cx                      ; save the number of sorts to do
        push    si                      ; save pointers
        push    di
        call    compare
        pop     di                      ; restore pointers
        pop     si
        pop     cx                      ; restore number of sorts to do

        add     si,12                   ; point to next elements to sort
        add     di,12
        loop    sort_start

        cmp     dx, 0                   ; any "swaps" done ?
        jne     sort_start0             ; if so, do it all again

        pop     ds                      ; restore DS
        ret
sort    endp


; called with si and di pointing to strings to compare
; swaps strings if required
; DX is non-zero if a swap happens

compare proc    near

        push    cx                      ; save cx because calling routine needs it
        push    si                      ; save pointers for the same reason
        push    di

        mov     cx,12                   ; length of string
        repe    cmpsb                   ; SI and DI will point to one byte PAST
                                        ; the first mismatch
        jne     mismatch

mismatch:
        dec     si                      ; point to the mismatch
        dec     di
        mov     al, [byte ptr di]       ; one byte in AL
        mov     ah, [byte ptr si]       ; one byte in AH
        cmp     al,ah
        jb      swap_required

        pop     di                      ; no swap required, so just return
        pop     si
        pop     cx
        ret

swap_required:
        pop     di                      ; restore the pointers to the start
        pop     si                      ;  of the strings
        push    si                      ; and save them again
        push    di
        mov     cx,12                   ; maximum length of a string
swap_loop:
        mov     al,[byte ptr di]        ; so begins an _ugly_ swap routine
        mov     ah,[byte ptr si]        ;  the only advantage of which is that
        mov     [byte ptr di],ah        ;  it is entirely register based
        mov     [byte ptr si],al
        inc     si                      ; next bytes to swap
        inc     di
        loop    swap_loop

        pop     di                      ; put everything back
        pop     si
        pop     cx
        mov     dx,1                    ; indicate a swap took place
        ret
compare endp

end
